package com.wp.file.controller;


import com.alibaba.fastjson.JSONObject;
import com.wp.file.common.R;
import com.wp.file.pojo.File;
import com.wp.file.pojo.Office;
import com.wp.file.pojo.User;
import com.wp.file.pojo.Warehouse;
import com.wp.file.service.FileService;
import com.wp.file.service.UserService;
import com.wp.file.service.WarehouseService;
import com.wp.file.utils.FileSort;
import com.wp.file.utils.FileUtil;
import com.wp.file.utils.FtpHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;


/**
 * onlyoffice接口 回调/打开/保存文海
 */
@Slf4j
@RestController
@RequestMapping("/api/office")
public class OfficeController {
    @Autowired
    private FileService fileService;
    @Autowired
    private WarehouseService warehouseService;
    @Autowired
    private UserService userService;
    @Value("${office.service.storepath}")
    private String STOREPATH;
    @Value("${office.service.onlyurl}")
    private String ONLYURL;
    @Value("${office.service.nginxurl}")
    private String NGINXURL;
    @Value("${office.service.backendurl}")
    private String BACKENDURL;
    //    @Value("${office.docservice.url.site}")
//    private String officeUrl;
//    @Value("${office.docservice.url.command}")
//    private String officeCommand;
//    @Value("${office.docservice.basepath}")
//    private String basePath;
//    @Value("${office.docservice.nginxurl}")
//    private String nginxUrl;



    /**
     * 获取文档服务地址
     */
    @GetMapping("/edit")                //仓库文件id
    public R<Office> editDocFile(@RequestParam Long warehouseId) {
        Warehouse warehouse = warehouseService.getById(warehouseId);
        if(warehouse == null){
            return R.error("该文件在服务器中不存在!");
        }
        Long fileId = warehouse.getFileId();
        File file = fileService.getById(fileId);
        User user = userService.getById(warehouse.getUserId());
        String url = NGINXURL+STOREPATH+file.getPath()+"/"+file.getStorename();
        Office office = new Office();
        office.setUrl(url);
        office.setTitle(warehouse.getDisplayName());
        office.setFileType(FileSort.getExtendName(warehouse.getDisplayName()));
        office.setUserId(warehouse.getUserId());
        office.setName(user.getEmail());
        office.setEditUrl(BACKENDURL+"/api/office/callback");
        return R.success(office);
        //找到文件拼出文档地址
        //0. nginxurl    http://192.168.20.4:6000/
        //1. basepath    warehouse
        //2. 日期         /2023-02-19
        //3. filename    2472394732.doc
    }

    @RequestMapping(path = "/callback", method = {RequestMethod.POST, RequestMethod.GET})
    public Map<Object,Object> callback(HttpServletRequest request,HttpServletResponse response)  {
        log.info("office开始回调!");
        HashMap<Object, Object> map = new HashMap<>();
        try {
            Scanner scanner = new Scanner(request.getInputStream()).useDelimiter("\\A");
            String body = scanner.hasNext() ? scanner.next() : "";
            JSONObject jsonObj = JSONObject.parseObject(body);
            String warehouseId = request.getParameter("id");
            log.info("文档在线编辑器回调参数{}",jsonObj);
            if((Integer) jsonObj.get("status") == 2){
                //保存变更后的文件
                String downloadUri = (String) jsonObj.get("url");//这里面是编辑后的文件的缓存地址cache
                String fileName = request.getParameter("filename");
                log.info("正在下载文件: "+fileName);
                URL url = new URL(downloadUri);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                InputStream stream1 = connection.getInputStream();
                String fileMd5 = DigestUtils.md5Hex(stream1);
                //上面计算了文件流的MD5的值现在开始要实现三个步骤
                //1.先上传该文件
                //2.把该文件的信息存入file数据库表
                //3.把该文件的warehouse的fileid切换成新的
                //先查一下之前该文件已经存在md5不
                File onefile = fileService.md5IsExist(fileMd5);
                if(onefile == null){
                    log.info(fileName+" 服务器未保存过该文件,正在开始上传~");
                    String newName = FileUtil.generateName(fileName);
                    InputStream inputStream = connection.getInputStream();
                    boolean uploadFlag = FtpHelper.uploadOfficeByStream(inputStream,newName);
                    if(!uploadFlag){ //上传失败时
                        log.info(fileName+" Upload failure");
                        //返回onlyoffice失败
                        map.put("error",1);
                        return map;
                    }
                    log.info(fileName+" Upload successfully");
                    onefile = new File();
                    //上传成功则存入数据库
                    onefile.setStorename(newName);
                    onefile.setPath("/" + LocalDate.now());
                    //使用IOUtils类计算InputStream的大小
                    long filesize = (long)  (IOUtils.toByteArray(inputStream).length / 1024.0);
                    onefile.setSize(filesize);
                    onefile.setMark(fileMd5);//暂时没定标识
                    fileService.save(onefile);
                }
                //更改warehouse的属性
                Warehouse warehouse = warehouseService.getById(warehouseId);
                warehouse.setSort(FileSort.getFileType(fileName));
                warehouse.setDisplayName(fileName);
                warehouse.setFileId(onefile.getId());
                warehouse.setDisplaySize(BigDecimal.valueOf(onefile.getSize())
                        .divide(BigDecimal.valueOf(1.0 * 1024 * 1024), 3, BigDecimal.ROUND_HALF_UP).doubleValue());
                warehouseService.updateById(warehouse);
                log.info(warehouseId+" 更新文档编辑完成!");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        map.put("error",0);//回调成功返回0
        return map;
    }











}
